package com.syni.mdd.yhd.common.all.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.WxPayApiConfig;
import com.ijpay.wxpay.model.RefundModel;
import com.syni.mdd.sjb.common.component.utils.common.utils.ArithUtil;
import com.syni.mdd.sjb.common.component.utils.common.utils.DateTimeUtils;
import com.syni.mdd.sjb.common.component.utils.common.utils.ResultMapHelper;
import com.syni.mdd.yhd.common.all.config.pay.wxPay.WxPayBeanFactory;
import com.syni.mdd.yhd.common.all.constants.Constants;
import com.syni.mdd.yhd.common.all.constants.ResultCode;
import com.syni.mdd.yhd.common.all.constants.ResultMsg;
import com.syni.mdd.yhd.common.all.controller.pay.wxPay.WxPayController;
import com.syni.mdd.yhd.common.all.dao.jpa.BmsPortOrderLogDao;
import com.syni.mdd.yhd.common.all.entity.BmsPortOrderLog;
import com.syni.mdd.yhd.common.all.entity.portBus.OrderRpcDto;
import com.syni.mdd.yhd.common.all.service.BmsPortOrderLogService;
import com.syni.mdd.yhd.common.all.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @className
 * @description TOO
 * @Author cfx
 * @DATE 2019/4/9 12:04
 * @VERSION 1.0
 **/
@Service
public class BmsPortOrderLogServiceImpl extends BaseService<BmsPortOrderLog, Integer> implements BmsPortOrderLogService {

    private Logger log = LoggerFactory.getLogger(getClass());

    @Value("${port.order.rpcUrl}")
    private String rpcUrl;
    private static String API_KEY = "rongtong";
    private static String API_SECRET = "1CAE66AB527D2980";
    //锁位
    public static String ORDER_STATUS_ONE = "0";
    //订单创建成功（可支付)
    public static String ORDER_STATUS_CAN_PAY = "1";
    //订单超时失效
    public static String ORDER_STATUS_OVERTIME = "2";
    //订单取消
    public static String ORDER_STATUS_CANCEL = "3";
    //已退款
    public static String ORDER_STATUS_RUFUND = "4";
    //已付款
    public static String ORDER_STATUS_PAY = "100";

    public static Map<String,Object> resultMsg = new LinkedHashMap<>();
    //未付款
    final Integer NO_PAY_STATUS = 0;
    //已付款
    final Integer PAY_STATUS = 1;
    //已退款
    final Integer REFUND_STATUS = 2;
    //支付成功
    final String PAY_SUCCESS = "1";
    //退款成功
    final String REFUND_SUCCESS = "2";

    @Autowired
    BmsPortOrderLogDao bmsPortOrderLogDao;

    @Autowired
    WxPayController wxPayController;

    static {
        resultMsg.put(ORDER_STATUS_ONE,"订单不可支付");
        resultMsg.put(ORDER_STATUS_OVERTIME,"订单超时失效");
        resultMsg.put(ORDER_STATUS_CANCEL,"订单取消");
        resultMsg.put(ORDER_STATUS_RUFUND,"订单已退款");
        resultMsg.put(ORDER_STATUS_PAY,"订单已付款");
    }

    @Override
    public BmsPortOrderLogDao getBaseDao() {
        return bmsPortOrderLogDao;
    }

    @Override
    public Map<String, Object> getPortBusOrder(String openId,String orderId, String orderType) {
        String orderSearchUrl = rpcUrl + "orderSearch";
        Map<String,Object> params = new LinkedHashMap<>();
        params.put("orderType",orderType);
        params.put("orderId",orderId);
        params.put("apiKey",API_KEY);
        params.put("sign",getMd5Sign(params));
        String reponseBody = RestTemplateUtils.getForEntity(orderSearchUrl,params);
        log.info("查询返回值：" + reponseBody);
        Map<String,Object> retMap = JSON.parseObject(reponseBody);
        if(retMap.containsKey("status") && ResultCode.CODE_NORMAL.equals(retMap.get("status").toString())){
            JSONArray jsonArray = (JSONArray) retMap.get("data");
            List<OrderRpcDto> orderRpcDtos = JSON.parseArray(jsonArray.toJSONString(),OrderRpcDto.class);
            Double total = 0d;
            if(orderRpcDtos != null && orderRpcDtos.size() > 0){
                //判断订单达到可支付状态
                for(OrderRpcDto orderRpcDto : orderRpcDtos){
                    if(!(orderRpcDto.getOrderStatus().equals(ORDER_STATUS_CAN_PAY))){
                        return ResultMapHelper.result(ResultCode.CODE_ERROR_100,resultMsg.get(orderRpcDto.getOrderStatus()).toString());
                    }
                    total = ArithUtil.add(total,Double.parseDouble(orderRpcDto.getOrderPrice()));
                }
                //同步创建这个订单
                OrderRpcDto rpcDto = orderRpcDtos.get(0);
                BmsPortOrderLog bmsPortOrderLog = syniCreateOrder(openId,orderType,rpcDto,total);
                bmsPortOrderLog.setServerTime(DateTimeUtils.converStringToDate(rpcDto.getTimestamp(),DateTimeUtils.DATE_PATTERN_TIMESTAMP));
                Map<String,Object> resultMap = new LinkedHashMap<>();
                resultMap.put("order",orderRpcDtos);
                resultMap.put("myDbOrder",bmsPortOrderLog);
                return ResultMapHelper.success(resultMap, ResultMsg.MSG_GET_SUCCESS);
            }
        }
        return ResultMapHelper.result(ResultCode.CODE_ERROR_100, ResultMsg.MSG_GET_FAIL);
    }

    private BmsPortOrderLog syniCreateOrder(String openId,String orderType,OrderRpcDto rpcDto,Double total) {
        Map<String,Object> conditionMap = new LinkedHashMap<>();
        conditionMap.put("openId",openId);
        conditionMap.put("orderId",rpcDto.getOrderId());
        conditionMap.put("orderType",orderType);
        List<BmsPortOrderLog> bmsPortOrderLogs = bmsPortOrderLogDao.findAll(new SpecificationUtils(conditionMap));
        BmsPortOrderLog bmsPortOrderLog = null;
        if(!(bmsPortOrderLogs != null && bmsPortOrderLogs.size() > 0)){
            bmsPortOrderLog = new BmsPortOrderLog();
            bmsPortOrderLog.setNewTime(new Date());
            bmsPortOrderLog.setOrderNo(OrderUtils.getRandomNo("KABS",20));
        }else {
            bmsPortOrderLog = bmsPortOrderLogs.get(0);
        }
        bmsPortOrderLog.setOrderId(rpcDto.getOrderId());
        bmsPortOrderLog.setOrderType(orderType);
        bmsPortOrderLog.setOpenId(openId);
        bmsPortOrderLog.setPayTotal(total);
        bmsPortOrderLog.setOrderTime(DateTimeUtils.converStringToDate(rpcDto.getOrderDate(),DateTimeUtils.DATE_PATTERN_TIMESTAMP));
        bmsPortOrderLogDao.save(bmsPortOrderLog);
        return bmsPortOrderLog;
    }

    public String getMd5Sign(Map<String,Object> paramMap){
        String str = JSON.toJSONString(paramMap) + API_SECRET;
        System.out.println("加密串：" + str);
        String sign =  WebUtils.MD5(str);
        System.out.println(sign.length());
        System.out.println(sign.toLowerCase());
        return sign.toLowerCase();
    }

    public boolean payNotice(String orderId,String orderType){
        String noticeUrl =  rpcUrl + "orderPayNotice";
        Map<String,Object> params = new LinkedHashMap<>();
        params.put("orderType",orderType);
        params.put("orderId",orderId);
        params.put("payStatus",PAY_SUCCESS);
        params.put("apiKey",API_KEY);
        params.put("sign",getMd5Sign(params));
        String reponseBody = RestTemplateUtils.getForEntity(noticeUrl,params);
        Map<String,Object> retMap = JSON.parseObject(reponseBody);
        if(retMap.containsKey("status") && ResultCode.CODE_NORMAL.equals(retMap.get("status").toString())){
            return true;
        }
        return false;
    }



    @Override
    public void payNotify(Map<String, String> params) {
        //更新自己数据库的订单
        String info = JSON.toJSONString(params);
        String out_trade_no = params.get("out_trade_no");
        String transaction_id = params.get("transaction_id");
        log.info("微信支付回调成功：" + JSON.toJSONString(params));
        //执行回调逻辑
        Date nowTime = new Date();
        try {
            //TODO
            // 修改订单状态
            // 已缴费----开始处理业务
            //orderLog.setCallBackIsSuccess(Constants.COMMON_FLAG_TRUE_INT);
            log.info(out_trade_no +" 用户已付款：.................................." );
            //查询订单
            BmsPortOrderLog bmsPortOrderLog = bmsPortOrderLogDao.findByOrderNo(out_trade_no);
            if(bmsPortOrderLog.getStatus() == NO_PAY_STATUS){
                bmsPortOrderLog.setTransactionId(transaction_id);
                bmsPortOrderLog.setStatus(PAY_STATUS);
                bmsPortOrderLogDao.save(bmsPortOrderLog);
                //通知口岸巴士付款成功
                if(payNotice(bmsPortOrderLog.getOrderId(),bmsPortOrderLog.getOrderType())){
                    log.info(".................通知口岸巴士成功..................");
                    bmsPortOrderLog.setPayNotice(Constants.COMMON_FLAG_TRUE_INT);
                    bmsPortOrderLogDao.save(bmsPortOrderLog);
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            log.error(e.getMessage(),e);
            //orderLog.setPayError(e.toString());
        }
    }

    @Override
    public boolean checkPortRpcApiKey(String apiKey) {
        return API_KEY.equals(apiKey);
    }

    @Override
    public boolean checkPortRpcRequest(Map<String, Object> paramsMap, String sign) {
        return getMd5Sign(paramsMap).equals(sign);
    }

    @Override
    public boolean refundOrder(String orderId, String orderType) {
        Map<String,Object> conditionMap = new LinkedHashMap<>();
        conditionMap.put("orderId",orderId);
        conditionMap.put("orderType",orderType);
        conditionMap.put("status",PAY_STATUS);
        List<BmsPortOrderLog> bmsPortOrderLogs = bmsPortOrderLogDao.findAll(new SpecificationUtils(conditionMap));
        if(bmsPortOrderLogs!= null && bmsPortOrderLogs.size() > 0){
            BmsPortOrderLog bmsPortOrderLog = bmsPortOrderLogs.get(0);
            //进行退款操作
            Double orderTotal = ArithUtil.round(ArithUtil.mul(bmsPortOrderLog.getPayTotal(),100),0);
            String orderTotalFee = String.valueOf(orderTotal.intValue());
            WxPayApiConfig wxPayApiConfig = wxPayController.getApiConfig(WxPayBeanFactory.PUBLIC_APP_CHANNEL);
            Map<String,String> params = RefundModel.builder()
                    .appid(wxPayApiConfig.getAppId())
                    .mch_id(wxPayApiConfig.getMchId())
                    .nonce_str(WxPayKit.generateStr())
                    .out_trade_no(bmsPortOrderLog.getOrderNo())
                    .out_refund_no(WxPayKit.generateStr())
                    .total_fee(orderTotalFee)
                    .refund_fee(orderTotalFee)
                    .notify_url(wxPayApiConfig.getDomain() + "/wxPay/refundNotify")
                    .build()
                    .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5);
            String xmlResult = WxPayApi.orderRefund(false, params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
            Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
            log.info("退款结果：" + JSON.toJSONString(result));
            String returnCode = result.get("return_code");
            String returnMsg = result.get("return_msg");
            if (WxPayKit.codeIsOk(returnCode) && "SUCCESS".equals(result.get("result_code"))) {
                bmsPortOrderLog.setStatus(REFUND_STATUS);
                bmsPortOrderLogDao.save(bmsPortOrderLog);
                return true;
            }
        }
        return false;
    }
}
